home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-04-22 | 18.2 KB | 609 lines | [TEXT/MPS ] |
- /*
- File: OpenDocX.cpp
-
- Contains: OpenDoc™ launcher application
-
- Owned by: Nick Pilch
-
- Copyright: © 1993 - 1996 by Apple Computer, Inc., all rights reserved.
-
- Change History (most recent first):
-
- <5> .04.1996 NP 1337753: Never show splash screen.
- <4> 3/14/96 NP 1258295: Displayed alert when app is
- double-clicked.
- <3> 1/15/96 TJ Cleaned Up
- <2> 1/15/96 JA 1269485: Display splash screen only 1st
- time launched.
- <26> 10/27/95 TÇ Remove code which checks for 32 bit
- addressing.
- <25> 10/25/95 TÇ 1281409 GM: OpenDoc needs an AboutBox.
- <24> 10/24/95 CC 1290114: Unload the scrap earlier to avoid
- segment loader errors or crash on low
- application heap space.
- <23> 9/29/95 eeh 1287262: use ShellDef.h
- <22> 8/26/95 TÇ 1269688 FB1: There is an unnecessary
- variable
- <21> 6/23/95 CC 1260976: Added UnloadScrap() after toolbox
- initialization.
- <20> 5/19/95 TÇ 1249396 (was BB) OpenDoc shell should
- serialize stationery creation., 1235942
- Launching the OpenDoc pref file causes a
- 1000 exception to be thrown, 1234877 BB:
- OpenDoc creates a bad document if
- stationary launch fails.
- <19> 4/15/95 TÇ #1236388 The launcher splash screen no
- longer goes away when a document window is
- opened
- <18> 4/7/95 eeh 1234548: check for 24-bit mode
- <17> 4/7/95 eeh 1221297: generalize ODOC handler to
- HandleRequiredEvent
- <16> 3/31/95 TÇ 1223445 Launcher barfs generating
- stationery from R/O library
- 1223493 BB: Creating a stationary under low
- disk space.
- 1226040 Launcher crashes if CFM68K is not
- installed.
- 1222903 Launcher doesn't check whether it
- could open the resource file for a library.
- 1233754 OpenDoc™ Launcher splash screen
- should use vers 2 resource.
- <15> 2/20/95 TÇ #1210979 BB: 5-$ Bugs need to be evaluated
- and removed from Shell
- #1221861 BB: Incomplete AOCE support needs
- to be removed from OpenDoc
- <14> 2/2/95 CG Added qd global.
- <13> 2/2/95 CG #1205177: "Editors" and "OpenDoc
- Libraries" folders are being registered
- with cfm (PPC only).
- <12> 1/9/95 NP 1209979: No changes. Check in to force
- rebuild for old runtime.
- <11> 1/6/95 jpa Fix error reporting in HandleOpenDocuments.
- [1198075]
- <10> 12/20/94 jpa Wait longer for CFM error event [1198075]
- <9> 12/5/94 jpa Catch CFM errors on document launch.
- Display splash screen. [1198075]
- <8> 10/12/94 TÇ 68K: check to see if an AEDesc is null
- before disposing
- <7> 9/15/94 TÇ #1183572 implement OpenDoc Shell PlugIns,
- got rid of a few warnings
- <6> 9/8/94 eeh #1185443: fix HandleOpenDocuments to
- preserve "special params".
- <5> 8/25/94 TÇ #1183223 Enabled launching of documents in
- folders other than that of the OpenDoc
- libraries
- <4> 7/25/94 TÇ added Jens' fixes for better error
- reporting and a few bug fixes of my own
- <3> 7/19/94 TÇ fixed a bug in ODXstrncpy
- <2> 7/14/94 TÇ changed resource copying code to using
- constant names instead of hard coded
- constants (for PPC)
- <1> 7/13/94 TÇ first checked in
- <0> 6/27/94 SV SOMverted
- <11> 4/19/94 TÇ Don't append a null character onto the end
- of the name of the stationery file because
- AFP chokes on it.
- <10> 4/18/94 TÇ Another fix for Symantec. This time to
- ODXstrncpy.
- <9> 4/18/94 HL Fixed Symantec Compilation.
- <8> 4/18/94 TÇ #1144379 Stationery model & generation have
- been fixed to enable dragging & dropping of
- stationery onto open documents.
- <7> 4/11/94 TÇ #1155854 Use CustomPutFile for Save A Copy.
- Checks to make sure document's resource
- fork was properly opened.
- <6> 3/24/94 eeh bug #1153053: Changes for PPC nativity (or
- is it nativeness...?)
- <5> 3/17/94 CG #1151392: Removed #include ConstDef.h.
- <4> 3/16/94 eeh bug #1149649 cont'd: CopyNonDPParams needed
- a return statement for Symantec
- <3> 3/16/94 eeh bug #1149649: added CopyNonDPParams
- <2> 3/10/94 eeh bug #1149632: added alias param to
- LaunchDocument()
- <14> 2/9/94 TÇ PowerPC header fixes
- <13> 1/18/94 TÇ conserve type and creator of documents
- being opened
- <12> 12/17/93 TÇ removed bogus semicolon at the end of the
- line " if (needUpdate);"
- <11> 12/17/93 eeh Code to install 'scsz' resource in
- documents.
- <10> 12/1/93 TÇ added calls to FlushInstructionCache()
- FlushDataCache() right before
- LaunchApplication to fix 040 data cache vs.
- instruction cache problem with copying
- resources as data then launching a document
- which uses them as code.
- <9> 11/30/93 TÇ added a cast to Ptr to pacify CFront
- <8> 11/23/93 TÇ mostly formatting
- <7> 10/28/93 TÇ use sizeof(FSSpec) instead of
- GetPtrSize(theDocument)
- <6> 10/27/93 TÇ more of the same.
- <5> 10/26/93 TÇ nil out fields of AEDesc.
- <4> 10/26/93 TÇ add code to construct 'ODOC' aevt and pass
- it along in the LaunchApplication call to
- the document being launched
- <3> 10/26/93 TÇ need to also use CODE 2 "32-bit blah blah
- blah" resource
- <2> 10/23/93 TÇ added code to verify and update CODE 0,
- CODE 1, and SIZE -1 resource in documents
- before they are launched
- <1> 10/18/93 TÇ first checked in
-
- To Do:
- In Progress:
-
- */
-
-
-
- /*
-
- This is the OpenDoc™ extension which is actually an application.
- The sole purpose of this extension is to satisfy the currnt "APPL" launching model in the Finder.
- When OpenDoc™ documents are double-clicked in the Finder,
- Finder notices that the creator of the documents is the same as this extension,
- then launches this extension with those documents.
- The OpenDoc™ extension verifies and fixes if necessary,
- the resources in the documents,
- then launches the documents using the ProcessManager directly and quits.
-
- */
-
- #define ppcinterfaces /* keeps GX headers quiet */
-
- #ifndef __TYPES__
- #include <Types.h>
- #endif
-
- #ifndef __GESTALTEQU__
- #include <GestaltEqu.h>
- #endif
-
- #ifndef __TEXTUTILS__
- #include <TextUtils.h>
- #endif
-
- #ifndef __OSEVENTS__
- #include <OSEvents.h>
- #endif
-
- #ifndef __QUICKDRAW__
- #include <Quickdraw.h>
- #endif
-
- #ifndef __FONTS__
- #include <Fonts.h>
- #endif
-
- #ifndef __FILES__
- #include <Files.h>
- #endif
-
- #ifndef __RESOURCES__
- #include <Resources.h>
- #endif
-
- #ifndef __EVENTS__
- #include <Events.h>
- #endif
-
- #ifndef __APPLEEVENTS__
- #include <AppleEvents.h>
- #endif
-
- #ifndef __DIALOGS__
- #include <Dialogs.h>
- #endif
-
- #ifndef __MENUS__
- #include <Menus.h>
- #endif
-
- #ifndef __OSUTILS__
- #include <OSUtils.h>
- #endif
-
- #ifndef __TOOLUTILS__
- #include <ToolUtils.h>
- #endif
-
- #ifndef __ERRORS__
- #include <Errors.h>
- #endif
-
- #ifndef __SCRAP__
- #include <Scrap.h>
- #endif
-
-
- #ifndef _REGISTER_
- #include <RegisterFileLibs.h>
- #endif
-
- #ifndef _SHELLDEF_
- #include "ShellDef.h"
- #endif
-
- #ifndef _ODPRCS_
- #include "ODPrcs.h"
- #endif
-
- #ifndef _ODXDEF_
- #include "ODXDef.h"
- #endif
-
- //==============================================================================
- // Constants
- //==============================================================================
-
- const short kLaunchFailedAlert = 130;
- const short kGenericLaunchFailedAlert = 129;
-
-
- const long kQuitDelay = 1 * 60; /* Wait 1 second for an Apple event */
- const long kWaitForErrorDelay = 8 * 60; /* Wait 8 seconds after trying to launch */
-
-
- #define SPLASHSCREEN 0 /* 1 enables splash screen, 0 disables */
-
- //==============================================================================
- // Globals
- //==============================================================================
-
- #ifndef __MWERKS__
- QDGlobals qd;
- #endif
-
- //==============================================================================
- // Macros
- //==============================================================================
-
- #define CHECK(EXPR) if((err=(EXPR)) == noErr) ; else return err
-
- //==============================================================================
- // Function Prototypes
- //==============================================================================
-
- static DialogPtr gSplashScreen = NULL;
- static long gQuitTime;
-
-
- void main( );
- static void MainEventLoop( );
- static Boolean FirstTimeLaunched( );
- static Boolean ColorScreen( );
- static void ReportError(StringPtr docName, OSErr err);
-
- //static OSErr CheckAppleEventForMissingParams(AppleEvent *theAppleEvent);
- extern "C" {
- static pascal OSErr HandleOpenAppEvent(AppleEvent *theAppleEvent,AppleEvent *reply,long refCon);
- static pascal OSErr HandleRequiredEvent(AppleEvent *theAppleEvent,AppleEvent *reply,long refCon);
- static pascal OSErr NoOpAEHandler(AppleEvent *theAppleEvent,AppleEvent *reply,long refCon);
- static pascal OSErr HandleLaunchFailed(AppleEvent *theAppleEvent,AppleEvent *reply,long refCon);
- }
-
- //==============================================================================
- // OpenDocX Main and Event Loop
- //==============================================================================
-
- //------------------------------------------------------------------------------
- // main
- //------------------------------------------------------------------------------
-
- void main(void)
- {
- MaxApplZone();
- MoreMasters();
-
- // The scrap is copied into our application heap when the process is launched,
- // occuping space otherwise used for launching documents.
- // If the scrap is just the right size (approx. 30K), there isn't enough
- // heap space left to launch a single document (the launcher will bail with
- // error -108). Worse, if the scrap is just the right size, around 40K,
- // InitWindows will hang the system. To avoid this, always unload the scrap.
- // Testing for a nil scrap handle seems to avoid a write to nil by UnloadScrap.
- // [cc]
- if ( InfoScrap()->scrapHandle != nil )
- UnloadScrap();
-
- InitGraf((Ptr)&qd.thePort);
- InitFonts();
- InitWindows();
- InitMenus();
- TEInit();
- InitDialogs(nil);
-
- long gestaltResponse;
- if ((Gestalt(gestaltCFMAttr, &gestaltResponse) != noErr) ||
- !(gestaltResponse & (1<<gestaltCFMPresent)))
- {
- ReportError("\p",fragMgrInitErr);
- return;
- }
-
- SetCursor(*GetCursor(watchCursor));
-
- AEEventHandlerUPP odocUPP = NewAEEventHandlerProc(HandleRequiredEvent);
- (void) AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
- odocUPP, 0, false);
- (void) AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
- odocUPP, 0, false);
-
- AEEventHandlerUPP openAppUPP = NewAEEventHandlerProc(HandleOpenAppEvent);
- (void) AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
- openAppUPP, 0, false); // no refcon, not system handler
-
- // AEEventHandlerUPP noOpUPP = NewAEEventHandlerProc(NoOpAEHandler);
- // (void) AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
- // noOpUPP, 0, false);
- // (void) AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
- // noOpUPP, 0, false);
-
- // Install a handler for both "launch-failed" notification events
- // so we can notify the user:
- AEEventHandlerUPP handleErrUPP = NewAEEventHandlerProc(HandleLaunchFailed);
- (void) AEInstallEventHandler(kCoreEventClass, kAEApplicationDied,
- handleErrUPP, 0, false);
- (void) AEInstallEventHandler(kCFMLaunchFailedEventClass, kCFMLaunchFailedEventID,
- handleErrUPP, 0, false);
-
- MainEventLoop();
- }
-
- //------------------------------------------------------------------------------
- // MainEventLoop
- //------------------------------------------------------------------------------
-
- static void MainEventLoop(void)
- {
- EventRecord anEvent;
-
- FlushEvents(everyEvent,0);
-
- #if SPLASHSCREEN
- if( !AreODDocumentsRunning() && FirstTimeLaunched() )
- gSplashScreen = ShowAboutScreen();
- #endif
-
- for( gQuitTime=TickCount()+kQuitDelay; TickCount()<gQuitTime; ) {
- (void) WaitNextEvent(everyEvent,&anEvent,5,(RgnHandle) nil);
- switch (anEvent.what)
- {
- case nullEvent:
- break;
-
- case osEvt:
- break;
-
- case kHighLevelEvent:
- AEProcessAppleEvent(&anEvent);
- break;
-
- default:
- if( IsDialogEvent(&anEvent) ) {
- DialogPtr whichDlog;
- short itemHit;
- if( DialogSelect(&anEvent,&whichDlog,&itemHit) && itemHit>0 )
- return;
- } else
- return;
- }
- }
- }
-
- //------------------------------------------------------------------------------
- // FirstTimeLaunched
- //------------------------------------------------------------------------------
-
- static Boolean FirstTimeLaunched( )
- {
- /* To figure out if this is the first time launched today, check the mod
- date of the "OpenDoc Preferences" file and compare it with today's date.
- If it's earlier, this is the first time today; set the mod date to the
- current date/time to signal that the launcher has run today. */
-
- FSSpec prefss;
- if( GetPrefsFileSpec(&prefss) != noErr )
- return true;
-
- CInfoPBRec pb;
- pb.hFileInfo.ioNamePtr = prefss.name;
- pb.hFileInfo.ioFDirIndex = 0;
- pb.hFileInfo.ioVRefNum = prefss.vRefNum;
- pb.hFileInfo.ioDirID = prefss.parID;
- OSErr error = PBGetCatInfoSync(&pb);
- if( error )
- return (error==fnfErr);
-
- // Convert mod-time to date format, and get current date:
- DateTimeRec prefsDate,curDate;
- SecondsToDate(pb.hFileInfo.ioFlMdDat,&prefsDate);
- GetTime(&curDate);
-
- // Compare:
- if( prefsDate.year==curDate.year && prefsDate.month==curDate.month && prefsDate.day==curDate.day )
- return false;
-
- // Not yet launched today. Bump mod date of file & return true:
- GetDateTime(&pb.hFileInfo.ioFlMdDat);
- pb.hFileInfo.ioDirID = prefss.parID;
- PBSetCatInfoSync(&pb);
- return true;
- }
-
- //==============================================================================
- // Error reporting
- //==============================================================================
-
- static void ReportError(StringPtr docName, OSErr err)
- {
- // If it's not legal to interact with the user, do nothing:
- if(AEInteractWithUser(0,NULL,NULL) == errAENoUserInteraction)
- return;
-
- // Bring myself to the front:
- ProcessSerialNumber psn;
- psn.highLongOfPSN = 0;
- psn.lowLongOfPSN = kCurrentProcess;
- SetFrontProcess(&psn);
-
- #if SPLASHSCREEN
- if( gSplashScreen ) {
- DisposeDialog(gSplashScreen);
- gSplashScreen = NULL;
- }
- #endif
-
- // Display the alert:
- short alertID = docName[0] ?kODXErrAlert :kODXAnonErrAlert;
- if( Get1Resource('ALRT',alertID) ) {
- unsigned char errStr[12];
- NumToString(err,errStr);
- ParamText(docName,errStr,NULL,NULL);
- InitCursor();
- StopAlert(alertID, NULL);
- } else {
- SysBeep(3);
- SysBeep(3);
- }
- }
-
- //==============================================================================
- // Apple Event handlers
- //==============================================================================
-
- //------------------------------------------------------------------------------
- // HandleRequiredEvent
- //------------------------------------------------------------------------------
-
- pascal OSErr HandleRequiredEvent(AppleEvent *theAppleEvent,
- AppleEvent * /*reply*/,long /*refCon*/)
- {
- AEDescList documentList;
- long documentCount;
- OSErr err = noErr;
- FSSpec theFSSpec;
-
- GetOpenDocBinaryFileSpec(kODNULL); // Sets up CFM search paths.
-
- CHECK(AEGetParamDesc(theAppleEvent,keyDirectObject,typeAEList,&documentList));
- CHECK(AECountItems(&documentList,&documentCount));
- DescType evtID;
- DescType ignoreType;
- Size ignoreActual;
- CHECK( AEGetAttributePtr( theAppleEvent, keyEventIDAttr, typeType,
- &ignoreType, &evtID, sizeof(evtID), &ignoreActual ));
-
- err = noErr;
-
- FSSpec seedFSSpec;
- seedFSSpec.name[0] = 0;
-
- AEDesc documentDesc;
-
- while (documentCount && (err == noErr))
- {
- AEKeyword theAEKeyword;
-
- CHECK(AEGetNthDesc(&documentList, documentCount, typeWildCard,
- &theAEKeyword, &documentDesc));
- if( GetDescFSSpec(&documentDesc,theFSSpec) != noErr )
- theFSSpec.name[0] = 0;
- err = VerifyAndLaunchDocumentStub(&documentDesc, kODNULL,
- kODNULL, evtID, &seedFSSpec);
- --documentCount;
- // Note: documentDesc gets leaked everytime through this loop
- // Doesn't matter since the launcher quits soon anyway.
- // And, the last documentDesc is necessary for launching a seed.
- }
-
- if (seedFSSpec.name[0] != 0)
- err= LaunchDocumentStub(&documentDesc, &seedFSSpec, kODNULL,
- kODNULL, kODNULL, evtID);
-
- if (err)
- ReportError(theFSSpec.name, err);
- else
- gQuitTime = TickCount() + kWaitForErrorDelay; // Give time for error to come back
-
- return err;
- }
-
- //------------------------------------------------------------------------------
- // HandleOpenAppEvent
- //
- // We only expect to handle open-document events. If we get an open-application
- // event, then the user must have double-clicked us. This doesn't do anything,
- // so we put up an alert telling him so.
- //------------------------------------------------------------------------------
-
- static pascal OSErr HandleOpenAppEvent(
- AppleEvent * /*theAppleEvent*/,
- AppleEvent * /*reply*/,
- long /*refCon*/)
- {
- SetCursor(&qd.arrow);
- CautionAlert(kODXDoubleClickAlert, NULL);
- return noErr;
- }
-
- //------------------------------------------------------------------------------
- // NoOpAEHandler
- //
- // NP: No reason to have this as far as I know
- //------------------------------------------------------------------------------
-
- static pascal OSErr NoOpAEHandler(
- AppleEvent * /*theAppleEvent*/,
- AppleEvent * /*reply*/,
- long /*refCon*/)
- {
- return(noErr);
- }
-
- static pascal OSErr
- HandleLaunchFailed( AppleEvent *ae, AppleEvent * /*reply*/, long /*refCon*/ )
- {
- // This is an Apple Event handler that catches launch-failed events.
-
- long launchError;
- unsigned char launchErrorString[12];
- Str255 appName, libName;
-
- GetLaunchFailedParams(ae, launchError,NULL,appName,libName);
- if( launchError==noErr )
- return noErr;
-
- NumToString(launchError,launchErrorString);
-
- {
- // Force myself to the foreground:
- ProcessSerialNumber psn = {0,kCurrentProcess};
- (void) SetFrontProcess(&psn);
- }
-
- #if SPLASHSCREEN
- if( gSplashScreen ) {
- DisposeDialog(gSplashScreen);
- gSplashScreen = NULL;
- }
- #endif
-
- InitCursor();
- if( appName[0]==0 ) {
- ParamText(NULL,launchErrorString,NULL,NULL);
- StopAlert(kGenericLaunchFailedAlert,NULL);
- } else {
- short index;
- Str255 errorDescription;
- if( launchError <= -2800 && launchError >= -2824 )
- index = 2-2800-launchError; // Maps -2800..-2824 -> 2..26
- else
- index = 1;
- GetIndString(errorDescription, kLaunchFailedErrStrings,index);
- ParamText(appName,errorDescription,libName,launchErrorString);
- StopAlert(kLaunchFailedAlert,NULL);
- }
- return noErr;
- }
-